const tool = require('../tools/tool')

module.exports = {
    async getCurrentUserDoQuestion(userId) {
        let status = (await tool.methods.chat().getStatus(userId)).status
        if (status === 1 || status === 3) {
            let latestExamCache = await tool.methods.exam().getLatestOneCache(userId)
            let latestExamOrReDo = await (async () => {
                if (latestExamCache.reDoCaches.length) {
                    return latestExamCache.reDoCaches[0]
                } else {
                    return latestExamCache
                }
            })()
            let latestQuestion = await tool.methods.exam().getLatestOneQuestionCache(status === 3, latestExamOrReDo.id)
            let re = await (async () => {
                if (status === 1) {
                    return await tool.dbf().selectWithParams(`select * from question where paperId = ? and \`index\` > ? order by \`index\` asc limit 0,1`, [latestExamCache.paperId, latestQuestion === undefined ? -1 : latestQuestion.questionInfo.index])
                }
                let chat = await tool.dbf().selectWithParams(`select * from chat where type = 2 and senderType = -1 and userId = ? order by createdAt desc limit 0,1`, [userId])
                chat = chat[0]
                if (chat) {
                    return await tool.dbf().selectWithParams(`select * from question where id = ?`, [chat.questionId])
                }
                return undefined
            })()
            re = re[0]
            return await format(re)
            // let latestChatMessage = await tool.methods.chat().getLatestChatMessage(userId)
            // if (!latestChatMessage) return undefined
            // if (latestChatMessage.type !== 2) return undefined
            // return await tool.methods.question().getSingle(latestChatMessage.questionId)
        }
        return undefined
    },
    async getSingle(questionId) {
        let re = await tool.dbf().selectWithParams(`select * from question where id = ?`, [questionId])
        re = re[0]
        if (re === undefined) return undefined
        return await format(re)
    },
    async add(categoryId, paperId, values) {
        values.optionA = values.options.A
        values.optionB = values.options.B
        values.optionC = values.options.C
        values.optionD = values.options.D
        values.optionAType = values.optionTypes.A
        values.optionBType = values.optionTypes.B
        values.optionCType = values.optionTypes.C
        values.optionDType = values.optionTypes.D
        try {
            values.answer = values.answer.join('')
        } catch (error) {

        }

        delete values.id
        return await tool.dbf().insertInto('question', {
            categoryId,
            paperId,
            ...values,
            modified: (typeof values.keywords === 'string' && values.keywords.length) ? 1 : 0
        })
    },
    async getList(paperId) {
        let data = await tool.dbf().selectWithParams(`select * from question where paperId = ? order by \`index\` ASC`, [paperId])
        for (let i = 0; i < data.length; i++) {
            data[i] = await format(data[i])
        }
        return data
    },
    async getFirstQuestion(paperId) {
        let data = await tool.dbf().selectWithParams(`select * from question where paperId = ? order by \`index\` ASC limit 0,1`, [paperId])
        data = data[0]
        return await format(data)
    },
    async update(questionId, values) {
        delete values.id
        await tool.dbf().updateById('question', questionId, values)
    },
    AIModify: {
        total1: 0,
        total2: 0,
        current: 0,
        finished: 0,
        status: 0,
        startAt: undefined,
        async run() {
            if (this.status) return
            let unmodifiedIds = await tool.dbf().selectWithParams(`select id from question where modified = 0 and img = '' and optionAType != 'image' and optionBType != 'image' and optionCType != 'image' and optionDType != 'image'`)
            let unmodifiedIds_image = await tool.dbf().selectWithParams(`select id from question where modified = 0 and (img !='' or optionAType = 'image' or optionBType = 'image' or optionCType = 'image' or optionDType = 'image')`)
            this.status = 1
            this.total1 = unmodifiedIds.length
            this.total2 = unmodifiedIds_image.length
            this.current = 1
            this.startAt = new Date()
            this.finished = 0
            let size = 20
            for (let i = 0; i < unmodifiedIds.length; i += size) {
                let current = unmodifiedIds.slice(i, i + size)
                let data = await tool.dbf().selectWithParams(`select * from question where ${(() => {
                    let str = ''
                    for (let i = 0; i < current.length; i++) {
                        if (str) str += ' or '
                        str += ` id = ${current[i].id} `
                    }
                    return str
                })()}`)
                let aire = await tool.openai.send(`请帮我把下面这个JSON的keywords字段加上关键词，关键词从题干中提取，关键词是经典的考试中常出现的通用简短简单宏观意思的关键词，每个关键词尽量一个字或者两个字非常常见的，每个问题至少10个关键词，意思尽量宏观，例如高中专科本科可用“学历”替代、德国美国中国可用“国家”替代，使用更为宏观的语言，例如专有名词，用英文逗号分隔开，返回一个对象JSON，格式为键是原来每个对象中的id的值，值为你加的关键词用英文逗号分割的字符串，保持中文，除了JSON之外千万不要有其他内容：${JSON.stringify(data)}`)
                try {
                    aire = tool.extractJsonFromString(aire)
                    for (let i1 = 0; i1 < data.length; i1++) {
                        let currentQuestion = data[i1]
                        let currentKeywords = aire[`${currentQuestion.id}`]
                        if (typeof currentKeywords === 'string') {
                            currentKeywords = currentKeywords.replaceAll('，', ',')
                            currentKeywords = currentKeywords.replaceAll(' ', '')
                        } else {
                            currentKeywords = ''
                        }
                        await tool.dbf().updateById('question', currentQuestion.id, {
                            modified: 1,
                            keywords: currentKeywords
                        })
                    }
                } catch (error) {

                }

                this.finished += current.length
                continue
            }
            this.current = 2
            for (let i = 0; i < unmodifiedIds_image.length; i++) {
                let current = unmodifiedIds_image[i]
                current = await tool.methods.question().getSingle(current.id)
                if (current === undefined) {
                    this.finished++
                    continue
                }
                let image = await tool.mergeLabeledImages(
                    current.img,
                    current.optionAType === 'image' ? current.optionA : undefined,
                    current.optionBType === 'image' ? current.optionB : undefined,
                    current.optionCType === 'image' ? current.optionC : undefined,
                    current.optionDType === 'image' ? current.optionD : undefined
                )
                let fileName = await tool.saveBase64Image(image)
                let re = await tool.openai.send(`请帮我把下面这一个题目加上关键词，关键词从题干中提取，关键词是经典的考试中常出现的通用简短简单宏观意思的关键词，每个关键词尽量一个字或者两个字非常常见的，每个问题至少10个关键词，意思尽量宏观，例如高中专科本科可用“学历”替代、德国美国中国可用“国家”替代，使用更为宏观的语言，例如专有名词，用英文逗号分隔开，返回一个JSON，这个JSON只有keywords这一个字段，值为你加的关键词用英文逗号分割的字符串，所有关键词拼接为一个字符串，用英文逗号分隔开，保持中文，除了JSON之外千万不要有其他内容 ${(() => {
                    return JSON.stringify({
                        stems: current.stems,
                        optionA: current.optionA,
                        optionB: current.optionB,
                        optionC: current.optionC,
                        optionD: current.optionD,
                        optionAType: current.optionAType,
                        optionBType: current.optionBType,
                        optionCType: current.optionCType,
                        optionDType: current.optionDType,
                        answer: current.answer,
                        analysis: current.analysis,
                    })
                })()}`, 'image', fileName)
                tool.deleteFile(fileName)
                try {
                    re = tool.extractJsonFromString(re)
                    re.keywords = re.keywords.replaceAll('，', ',')
                    re.keywords = re.keywords.replaceAll(' ', '')
                    await tool.dbf().updateById('question', current.id, {
                        modified: 1,
                        keywords: re.keywords
                    })
                } catch (error) {
                    console.log(error)
                }
                this.finished++
                continue
            }
            this.startAt = undefined
            this.status = 0
        },
        async getStatus() {
            let unmodified = (await tool.dbf().select(`select count(*) as total from question where modified = 0`))[0].total
            if (!this.startAt) return {
                running: false,
                unmodified
            }
            return {
                running: this.status ? true : false,
                currentType: this.current,
                total1: this.total1,
                total2: this.total2,
                finished: this.finished,
                total: this.total1 + this.total2,
                usedTime: tool.formatTimeDifference(new Date(), this.startAt),
                finishedPer: parseInt(this.finished / (this.total1 + this.total2) * 10000) / 100,
                lastTime: this.finished === 0 ? '正在计算' : tool.formatTimeDifference(0, (new Date() - this.startAt) / (this.finished / (this.total1 + this.total2)) * (1 - this.finished / (this.total1 + this.total2)))
            }
        },
        start() {
            (async () => {
                try {
                    await this.run()
                } catch (error) {
                    this.startAt = undefined
                    console.log(error)
                }
            })()
        },
        async resetAll() {
            await tool.dbf().exe(`update question set modified = 0, keywords = ''`)
        }
    },
    async getQuestionString(questionId) {
        let re = await this.getSingle(questionId)
        if (!re) return ''
        return `题干：${re.stems}
        选项A：${re.optionAType === '选择' ? re.optionA : ''}
        选项B：${re.optionBType === '选择' ? re.optionB : ''}
        选项C：${re.optionCType === '选择' ? re.optionC : ''}
        选项D：${re.optionDType === '选择' ? re.optionD : ''}
        答案：${re.answer}
        解析：${re.analysis}
        
        `
    },
    AIParse: {
        onceStringLength: 512,
        running: false,
        preToParseDocList: [],
        addDoc(fileName, answerFileName, paperName, categoryId, isEassy) {
            this.preToParseDocList.push({
                id: new Date(),
                fileName,
                answerFileName,
                status: 0,
                downloadFileName: '',
                err: '',
                paperName,
                categoryId,
                isEassy
            })
            this.run()
        },
        async run() {
            if (this.running) return
            this.running = true
            while (1) {
                if (this.preToParseDocList.length === 0) {
                    this.running = false
                    return
                }
                let item = this.preToParseDocList[0]
                item.status = 1
                try {
                    let re = await this.parseNotEassy(item.fileName, item.answerFileName)
                    item.downloadFileName = re
                    item.status = 2
                    await this.addFinishedDoc(this.preToParseDocList[0])
                } catch (error) {
                    item.err = error.toString()
                    item.status = -1
                    await this.addFinishedDoc(this.preToParseDocList[0])
                }
                this.preToParseDocList.shift()
                setTimeout(() => {
                    tool.deleteFile(item.fileName)
                    tool.deleteFile(item.answerFileName)
                }, 100);
            }
        },
        progress: 0,
        async parseNotEassy(fileName, answerFileName) {
            let image = await tool.extractImagesFromFile(`./files/${fileName}`)
            console.log(image)
            let re = await tool.readDocumentText(`./files/${fileName}`)
            let answer_re = await tool.readDocumentText(`./files/${answerFileName}`)
            let parsed = []
            let parsedAnswer = []
            this.progress = 0
            if (typeof re === 'string') {
                re = re.replaceAll('\n', '')
                re = re.replaceAll(' ', '')
                re = re.replaceAll('\t', ' ')

                let aire_question_num
                try {
                    aire_question_num = await tool.openai.send(`这个文档里面有几道题？直接返回给我一个JSON，有一个num字段表示文档中题目的数量，JSON两端不要有其他的内容，文档：${re}`)
                    aire_question_num = tool.extractJsonFromString(aire_question_num)
                    aire_question_num = aire_question_num.num
                    if (isNaN(aire_question_num)) throw 'num应为数字'
                } catch (error) {

                }

                let aire_question_num2
                try {
                    aire_question_num2 = await tool.openai.send(`这个文档里面有几道题？直接返回给我一个JSON，有一个num字段表示文档中题目的数量，JSON两端不要有其他的内容，文档：${re}`)
                    aire_question_num2 = tool.extractJsonFromString(aire_question_num2)
                    aire_question_num2 = aire_question_num2.num
                    if (isNaN(aire_question_num2)) throw 'num应为数字'
                } catch (error) {

                }

                let aire_question_num3
                try {
                    aire_question_num3 = await tool.openai.send(`这个文档里面有几道题？直接返回给我一个JSON，有一个num字段表示文档中题目的数量，JSON两端不要有其他的内容，文档：${re}`)
                    aire_question_num3 = tool.extractJsonFromString(aire_question_num3)
                    aire_question_num3 = aire_question_num3.num
                    if (isNaN(aire_question_num3)) throw 'num应为数字'
                } catch (error) {

                }

                let nums = {}
                if (nums[aire_question_num] === undefined) {
                    nums[aire_question_num] = 1
                } else {
                    nums[aire_question_num]++
                }
                if (nums[aire_question_num2] === undefined) {
                    nums[aire_question_num2] = 1
                } else {
                    nums[aire_question_num2]++
                }
                if (nums[aire_question_num3] === undefined) {
                    nums[aire_question_num3] = 1
                } else {
                    nums[aire_question_num3]++
                }

                let maxValue = [aire_question_num, aire_question_num2, aire_question_num3].sort((a, b) => {
                    return b - a
                })[0]

                let currentStart = 1
                while (1) {
                    if (currentStart <= maxValue) {
                        let c = maxValue - currentStart
                        if (c > 5) c = 5
                        try {
                            let aire_questions = await tool.openai.send(`帮我返回这个文档的${currentStart}到${currentStart + c}个题目，返回的形式为一个JSON，有一个arr字段，这个字段是一个对象数组，每个对象代表一个题目，不要读取例题，有index字段表示题号（和原文档中保持一致）、stems字段（表示题干）、optionA（表示选项A的内容）、optionB、optionC、optionD，如果有些题目前面有段落描述情景，那么情景的内容也需要加入到之后的每个每个每个相关的题目的题干字符串中的首部，对于有无图片的判断务必严谨，每个题目都各自还有一个keywords关键词字段（关键词从题干中提取，关键词是经典的考试中常出现的通用简短简单宏观意思的关键词，每个关键词尽量一个字或者两个字非常常见的，每个问题至少10个关键词，意思尽量宏观，例如高中专科本科可用“学历”替代、德国美国中国可用“国家”替代，使用更为宏观的语言，例如专有名词，用英文逗号分隔开），JSON两端不要有其他的内容，严格的按照我说的规范进行读取，你不能自由发挥，题目文档：${re}`)
                            aire_questions = tool.extractJsonFromString(aire_questions)
                            parsed = [...parsed, ...aire_questions.arr]
                            currentStart += aire_questions.arr.length
                        } catch (error) {
                            continue
                        }
                    } else {
                        break
                    }
                }
            } else {
                return
            }
            if (typeof answer_re === 'string') {
                re = answer_re
                re = re.replaceAll('\n', '')
                re = re.replaceAll(' ', '')
                re = re.replaceAll('\t', ' ')

                let aire_question_num
                try {
                    aire_question_num = await tool.openai.send(`这个文档里面有几道题？直接返回给我一个JSON，有一个num字段表示文档中题目的数量，JSON两端不要有其他的内容，文档：${re}`)
                    aire_question_num = tool.extractJsonFromString(aire_question_num)
                    aire_question_num = aire_question_num.num
                    if (isNaN(aire_question_num)) throw 'num应为数字'
                } catch (error) {

                }

                let aire_question_num2
                try {
                    aire_question_num2 = await tool.openai.send(`这个文档里面有几道题？直接返回给我一个JSON，有一个num字段表示文档中题目的数量，JSON两端不要有其他的内容，文档：${re}`)
                    aire_question_num2 = tool.extractJsonFromString(aire_question_num2)
                    aire_question_num2 = aire_question_num2.num
                    if (isNaN(aire_question_num2)) throw 'num应为数字'
                } catch (error) {

                }

                let aire_question_num3
                try {
                    aire_question_num3 = await tool.openai.send(`这个文档里面有几道题？直接返回给我一个JSON，有一个num字段表示文档中题目的数量，JSON两端不要有其他的内容，文档：${re}`)
                    aire_question_num3 = tool.extractJsonFromString(aire_question_num3)
                    aire_question_num3 = aire_question_num3.num
                    if (isNaN(aire_question_num3)) throw 'num应为数字'
                } catch (error) {

                }

                let nums = {}
                if (nums[aire_question_num] === undefined) {
                    nums[aire_question_num] = 1
                } else {
                    nums[aire_question_num]++
                }
                if (nums[aire_question_num2] === undefined) {
                    nums[aire_question_num2] = 1
                } else {
                    nums[aire_question_num2]++
                }
                if (nums[aire_question_num3] === undefined) {
                    nums[aire_question_num3] = 1
                } else {
                    nums[aire_question_num3]++
                }

                let maxValue = [aire_question_num, aire_question_num2, aire_question_num3].sort((a, b) => {
                    return b - a
                })[0]

                let currentStart = 1
                while (1) {
                    if (currentStart <= maxValue) {
                        let c = maxValue - currentStart
                        if (c > 5) c = 5
                        try {
                            let aire_questions = await tool.openai.send(`帮我返回这个文档的${currentStart}到${currentStart + c}个题目的解析和答案，返回的形式为一个JSON，有一个arr字段，这个字段是一个对象数组，每个对象代表一个题目，有index字段表示题号（和原文档中保持一致）、analysis字段（表示解析）、answer（表示答案），JSON两端不要有其他的内容，严格的按照我说的规范进行读取，你不能自由发挥，题目答案解析文档：${re}`)
                            aire_questions = tool.extractJsonFromString(aire_questions)
                            parsedAnswer = [...parsedAnswer, ...aire_questions.arr]
                            currentStart += aire_questions.arr.length
                        } catch (error) {
                            continue
                        }
                    } else {
                        break
                    }
                }
            } else {
                return
            }
            for (let i = 0; i < parsed.length; i++) {
                parsed[i].index = parseInt(parsed[i].index)
            }
            for (let i = 0; i < parsedAnswer.length; i++) {
                parsedAnswer[i].index = parseInt(parsedAnswer[i].index)
                for (let i1 = 0; i1 < parsed.length; i1++) {
                    if (parsed[i1].index === parsedAnswer[i].index) {
                        parsed[i1] = {
                            type: '选择',
                            optionAType: 'multipleText',
                            optionBType: 'multipleText',
                            optionCType: 'multipleText',
                            optionDType: 'multipleText',
                            ...parsedAnswer[i],
                            ...parsed[i1],
                        }
                        break
                    }
                }
            }
            this.progress = 1

            // 给parsed添加有图的预测
            for (let i = 0; i < parsed.length; i++) {
                let pt = /-image-|-?\d+-/
                parsed[i] = (() => {
                    let item = parsed[i]
                    if ((typeof item.stems === 'string' && pt.test(item.stems)) || !item.stems) {
                        item.haveImg = true
                    }
                    if (item.type === '选择') {
                        if ((typeof item.optionA === 'string' && pt.test(item.optionA)) || !item.optionA || item.optionAType === 'image') {
                            item.optionAType = 'image'
                        }
                        if ((typeof item.optionB === 'string' && pt.test(item.optionB)) || !item.optionB || item.optionBType === 'image') {
                            item.optionBType = 'image'
                        }
                        if ((typeof item.optionC === 'string' && pt.test(item.optionC)) || !item.optionC || item.optionCType === 'image') {
                            item.optionCType = 'image'
                        }
                        if ((typeof item.optionD === 'string' && pt.test(item.optionD)) || !item.optionD || item.optionDType === 'image') {
                            item.optionDType = 'image'
                        }
                    }
                    return item
                })()
            }

            return tool.saveStringToRandomFile(JSON.stringify({
                parsed,
                image
            }))
        },
        async getDisplay() {
            return {
                progress: this.progress,
                preToParseDocList: await (async () => {
                    let re = tool.deepCopy(this.preToParseDocList)
                    for (let i = 0; i < re.length; i++)re[i].categoryInfo = await tool.methods.category().getSingle(re[i].categoryId)
                    return re
                })(),
                finishedParseDocList: await this.getFinishedDocList(),
                running: this.running
            }
        },
        async addFinishedDoc(item) {
            let list = await tool.methods.settings().getItem('AIParseFinishedDocList')
            list.push({
                ...item,
                id: item.id,
                downloadFileName: item.downloadFileName,
                paperName: item.paperName,
                categoryId: item.categoryId
            })
            await tool.methods.settings().setItem('AIParseFinishedDocList', list)
        },
        async getFinishedDocList() {
            let re = await tool.methods.settings().getItem('AIParseFinishedDocList')
            for (let i = 0; i < re.length; i++) {
                re[i].categoryInfo = await tool.methods.category().getSingle(re[i].categoryId)
            }
            return re
        },
        async deleteFinished(id) {
            let list = await this.getFinishedDocList()
            for (let i = 0; i < list.length; i++) {
                if (list[i].id === id) {
                    await tool.deleteFile(list[i].downloadFileName)
                }
            }
            list = list.filter(item => item.id !== id)
            await tool.methods.settings().setItem('AIParseFinishedDocList', list)
        }
    },
    allQuestionString: {
        _str: '',
        async get() {
            let str = ''
            let papers = await tool.dbf().select(`select * from paper`)
            for (let i = 0; i < papers.length; i++) {
                let currentStr = ''
                let questions = await tool.dbf().selectWithParams(`select * from question where paperId = ?`, [papers[i].id])
                let paperInfo = await tool.dbf().selectWithParams(`select * from paper where id = ?`, [papers[i].id])
                paperInfo = paperInfo[0]
                let categoryInfo = await tool.methods.category().getSingle(paperInfo.categoryId)
                if(!categoryInfo)continue
                currentStr += categoryInfo.name + ' ' + paperInfo.name + '：'
                for (let i1 = 0; i1 < questions.length; i1++) {
                    currentStr += `第${questions[i1].index}题：${questions[i1].stems}。类型为${questions[i1].type}
                    ${(() => {
                            if (questions[i1].type === '选择') {
                                let re = ''
                                re += `选项A: ${ questions[i1].optionA }`
                                re += `选项B: ${ questions[i1].optionB }`
                                re += `选项C: ${ questions[i1].optionC }`
                                re += `选项D: ${ questions[i1].optionD }`
                                return re
                            } else {
                                let re = ''
                                return re
                            }
                        })()}
                    答案为：${ questions[i1].answer }
                    解析为：${ questions[i1].analysis }`
                }
                str+=currentStr
            }
            this._str = str
        }
    }
}

function parseNumberedSections(input = '') {
    const result = {};

    let splits = [
        {
            c: 'ꙮ',
            num: input.split('ꙮ').length - 1
        },
    ]
    splits = splits.sort((a, b) => {
        return b.num - a.num
    })
    let split = splits[0].c

    let current = 1
    while (1) {
        let str = `${current}${split}`
        let index = input.indexOf(str)
        if (index === -1) break
        input = input.slice(index + str.length)

        let nextStr = `${current + 1}${split}`
        let nextIndex = input.indexOf(nextStr)

        result[current] = (() => {
            if (nextIndex === -1) {
                return input
            } else {
                return input.slice(0, nextIndex)
            }
        })()

        current++
    }

    return result;
}

function parseSingleQuestion(input = '', index) {
    index = parseInt(index)
    let re = {
        stems: '',
        options: {},
        analysis: '',
        type: '选择',
        img: '',
        optionTypes: {
            'A': 'multipleText', 'B': 'multipleText', 'C': 'multipleText', 'D': 'multipleText'
        }
    }

    let splits = [
        {
            c: '⁂',
            num: input.split('⁂').length - 1
        }
    ]
    splits = splits.sort((a, b) => {
        return b.num - a.num
    })
    let split = splits[0].c

    let checks = [`A${split}`, `B${split}`, `C${split}`, `D${split}`, '解析']
    for (let i = 0; i < checks.length; i++) {
        let index = (() => {
            if (checks[i] === '解析') {
                let in1 = input.indexOf('解析')
                let in2 = input.indexOf('解答')
                if (in1 === -1 && in2 === -1) return -1
                if (in1 === -1) return in2
                return in1
            } else {
                return input.indexOf(checks[i])
            }
        })()
        if (index > -1) {
            checks[i] = {
                item: checks[i],
                index: index
            }
        }
    }
    checks = checks.filter(item => typeof (item) !== 'string').sort((a, b) => {
        return a.index - b.index
    })
    if (checks.length) {
        re.stems = input.slice(0, checks[0].index)
        for (let i = 0; i < checks.length; i++) {
            let str
            if (i === checks.length - 1) {
                str = input.slice(checks[i].index + checks[i].item.length)
            } else {
                str = input.slice(checks[i].index + checks[i].item.length, checks[i + 1].index)
            }

            str = str.replaceAll('】', '')
            str = str.replaceAll('【', '')
            str = str.trimStart()
            str = str.trimEnd()

            if (checks[i].item === '解析') {
                re.analysis = str
            } else {
                let tihao = `${index}.`
                if (str.indexOf(tihao) !== 0) str = str.split(tihao)[0]
                re.options[checks[i].item.replaceAll('⁂', '').replaceAll('⁂', '')] = str
            }
        }
    } else {
        re.stems = input
    }
    return re
}

async function format(item) {
    item.options = {
        A: item.optionA,
        B: item.optionB,
        C: item.optionC,
        D: item.optionD,
    }
    item.optionTypes = {
        A: item.optionAType,
        B: item.optionBType,
        C: item.optionCType,
        D: item.optionDType,
    }
    return item
}